<?php

require_once(WSB_MODULES_PATH . 'sherpa/models/BasketGateway.php');
require_once(WSB_MODULES_PATH . 'sherpa/models/OrderGateway.php');
require_once(WSB_MODULES_PATH . 'sherpa/models/CouponGateway.php');
require_once(WSB_MODULES_PATH . 'sherpa/models/AddressGateway.php');
require_once(WSB_MODULES_PATH . 'sherpa/forms/Address.php');

class Sherpa_CheckoutController extends WSB_Xtension_Extension
{

	/**
	 * @var Zend_Session_Namespace
	 */
	private $_session;

	/**
	 * @var Member_Model_DbTable_Feuser_Row
	 */
	private $_feuser;

	/**
	 * @var boolean
	 */
	private $_test = false;

	/**
	 * @return string
	 */
	public function renderForBackend()
	{
		return get_class($this);
	}

	/**
	 * Initialisierung
	 */
	public function init()
	{
		$this->_session = new Zend_Session_Namespace('Sherpa_Checkout');
		if(is_null($this->_session->billingAddress)) {
			$this->_session->billingAddress = array();
		}
		if(is_null($this->_session->shippingAddress)) {
			$this->_session->shippingAddress = array();
		}
		if(is_null($this->_session->billingAddressId)) {
			$this->_session->billingAddressId = 0;
		}
		if(is_null($this->_session->shippingAddressId)) {
 			$this->_session->shippingAddressId = 0;
		}
		if(is_null($this->_session->sameAsShippingAddress)) {
			$this->_session->sameAsShippingAddress = 0;
		}

		$auth = WSB_Auth_Frontend::getInstance();
		if($auth->hasIdentity()) {
			$this->_feuser = $auth->getIdentity();
		}
		if(!$this->_isValid()) {
			$this->_redirectToCart();
		}
		$this->initTranslate();
	}

	/**
	 * Zahlungsinformationen
	 *
	 */
	public function indexAction()
	{
		$this->shippingAddressAction();
	}

	/**
	 * Lieferadresse
	 *
	 * @param Sherpa_Form_Address $form
	 */
	public function shippingAddressAction(Sherpa_Form_Address $form = null)
	{
		$request = $this->getRequest();
		if(is_null($form)) {
			$form = new Sherpa_Form_Address();
		}
		if($this->_isAnonymousCheckout()) {
			//$form->setDefaults(array_merge($this->_session->shippingAddress, $request->getPost()));
			$form->setDefaults($this->_session->shippingAddress);
		}
		$form->removeDecorator('Form');
		$this->assignToView('sameAsShippingAddress', $request->getPost('sameAsShippingAddress', $this->_session->sameAsShippingAddress));
		$this->assignToView('addresses', $this->_getFeuserAddresses());
		$this->assignToView('form', $form);
		$this->renderView('checkout/shipping_address.phtml');
	}

	/**
	 * Lieferadresse (Validierung, Sichern, Session)
	 */
	public function addShippingAddressAction()
	{
		$request = $this->getRequest();
		$btnSelectAddress = $request->getPost('btnSelectAddress', array());
		$shippingAddressId = empty($btnSelectAddress) ? 0 : key($btnSelectAddress);
		$this->_session->sameAsShippingAddress = $request->getPost('sameAsShippingAddress');

		$addresses = $this->_getFeuserAddresses();

		$form = new Sherpa_Form_Address();
		$form->populate($request->getPost());

		// Neue Adresse
		if($this->_createButtonClicked() && $form->isValid($request->getPost())) {
			$shippingAddress = $form->getValues();
			unset($shippingAddress['btnCreateAddress']);
			unset($shippingAddress['btnCreateAddress_x']);
			unset($shippingAddress['btnCreateAddress_y']);
			// Anonymer Checkout
			if($this->_isAnonymousCheckout()) {
				$this->_session->shippingAddress = $shippingAddress;
			} else {
				$gateway = new Sherpa_Model_AddressGateway();
				$lastInsertId = $gateway->addAddress($shippingAddress);
				$this->_session->shippingAddressId = $lastInsertId;
			}
			$this->billingAddressAction();
		// Adresse ausgewaehlt
		} elseif(!empty($shippingAddressId) && $addresses->contains('id', $shippingAddressId)) {
			$this->_session->shippingAddressId = $shippingAddressId;
			$this->billingAddressAction();
		} else {
			$this->shippingAddressAction($form);
		}
	}

	/**
	 * Rechnungsadresse
	 *
	 * @param Sherpa_Form_Address $form
	 */
	public function billingAddressAction(Sherpa_Form_Address $form = null)
	{
		if(empty($this->_session->sameAsShippingAddress)) {

			$request = $this->getRequest();
			if(is_null($form)) {
				$form = new Sherpa_Form_Address();
			}
			if($this->_isAnonymousCheckout()) {
				//$form->setDefaults(array_merge($this->_session->billingAddress, $request->getPost()));
				$form->setDefaults($this->_session->billingAddress);
			}
			$form->removeDecorator('Form');
			$this->assignToView('addresses', $this->_getFeuserAddresses());
			$this->assignToView('form', $form);
			$this->renderView('checkout/billing_address.phtml');

		} else {
			$this->_session->billingAddressId = $this->_session->shippingAddressId;
			$this->_session->billingAddress = $this->_session->shippingAddress;
			$this->summaryAction();
		}
	}

	/**
	 * Rechnungsadresse (Validierung, Sichern, Session)
	 */
	public function addBillingAddressAction()
	{
		$request = $this->getRequest();
		$btnSelectAddress = $request->getPost('btnSelectAddress', array());
		$billingAddressId = empty($btnSelectAddress) ? 0 : key($btnSelectAddress);

		$addresses = $this->_getFeuserAddresses();

		$form = new Sherpa_Form_Address();
		$form->populate($request->getPost());

		// Neue Adresse
		if($this->_createButtonClicked() && $form->isValid($request->getPost())) {
			$billingAddress = $form->getValues();
			unset($billingAddress['btnCreateAddress']);
			unset($billingAddress['btnCreateAddress_x']);
			unset($billingAddress['btnCreateAddress_y']);
			$this->_session->billingAddress = $billingAddress;
			$this->summaryAction();
		// Adresse ausgewaehlt
		} elseif(!empty($billingAddressId) && $addresses->contains('id', $billingAddressId)) {
			$this->_session->billingAddressId = $billingAddressId;
			$this->summaryAction();
		} else {
			$this->billingAddressAction($form);
		}
	}

	/**
	 * Zusammenfassung
	 *
	 * @param array $errors
	 */
	public function summaryAction(array $errors = array())
	{
		// Validierung der Session Daten
		if(!$this->_validateSessionAddressData()) {
			$this->renderView('checkout/error.phtml');
			return;
		}

		// Sessiondaten dem View zuweisen
		$this->_assignSessionDataToView();
		$medialistOptions = array(
		  '' => '',
		  'Prospekt (Post)' => 'Prospekt (Post)',
		  '20 Minuten' => '20 Minuten',
		  '20 Minuten Online' => '20 Minuten Online',
		  'Schweizer Familie' => 'Schweizer Familie',
		  'Blick' => 'Blick',
		  'Blick Online' => 'Blick Online',
		  'SoBlick' => 'SoBlick',
		  'TV täglich' => 'TV täglich',
		  'Annabelle' => 'Annabelle',
		  'Walliser Bote' => 'Walliser Bote',
		  'Bündner Nachrichten' => 'Bündner Nachrichten',
		  'SAC Die Alpen' => 'SAC Die Alpen',
		  'Radio' => 'Radio',
		  'Google' => 'Google',
		  'Tagespresse' => 'Tagespresse',
		  'Magazin' => 'Magazin',
		  'Newsletter' => 'Newsletter',
		  'Empfehlung' => 'Empfehlung',
		  'Basler Zeitung' => 'Basler Zeitung'
		);
        $this->assignToView('medialistOptions', $medialistOptions);
        $this->assignToView('medialist', $this->getRequest()->getPost('medialist', ''));
		$this->assignToView('errors', $errors);
		$this->assignToView('products', $this->_getBasketProducts());
		$this->assignToView('coupon', $this->_getCoupon());
		$this->renderView('checkout/summary.phtml');
	}

	/**
	 * Bestellung auslösen
	 */
	public function orderAction()
	{
		// Validierung der Session Daten
		if(!$this->_validateSessionAddressData()) {
			$this->renderView('checkout/error.phtml');
			return;
		}

		// Sessiondaten dem View zuweisen
		$this->_assignSessionDataToView();

		$request = $this->getRequest();

		// Validierung
		$errors = array();
		$agb = intval($request->getPost('agb', 0));
		$medialist = trim($request->getPost('medialist', ''));
		if(empty($agb)) {
			$errors['agb'] = 'sherpaAGBerror';
		}
		if(empty($medialist)) {
			$errors['medialist'] = 'sherpaMedialistError';
		}

		if($request->isPost() && empty($errors)) {

			$products = $this->_getBasketProducts();
			$subtotal = $products->calculateSubtotal();

            // @todo: Soll das Subtotal oder das Total in der Bestellung
            // gespeichert werden?
    		$hooks = WSB_Hooks::instance();
    		$hooks->execute('Sherpa/CheckoutController/OrderAction/Subtotal', $subtotal, $products);

			$coupon = $this->_getCoupon();
			$couponIsValid = !$coupon->isEmpty() && $coupon->isValid($subtotal);
			$basketGateway = new Sherpa_Model_BasketGateway();
			$basket = $basketGateway->fetchBasket();

			// Order-Model erzeugen und mit allen Benutzerdaten fuellen,
			$shippingAddress = $this->_getShippingAddressFromSession();
			$billingAddress = $this->_getBillingAddressFromSession();
			$order = new Sherpa_Model_Order();
			$order->setMedialist($medialist);
			$order->setSubtotal($subtotal);
			$order->setShippingAddress($shippingAddress);
			$order->setBillingAddress($billingAddress);
			if($this->_feuser instanceof Member_Model_DbTable_Feuser_Row) {
				$order->setFeuserId($this->_feuser->id);
			}
			if($couponIsValid) {
				$order->setCouponId($coupon->getId());
			}
			$order->setBasketId($basket->getId());

			// Bestellung speichern
			$orderGateway = new Sherpa_Model_OrderGateway();
			if($this->_test) {
				$lastInsertOrderId = 0;
				$orderId = '123456789';
			} else {
				$lastInsertOrderId = $orderGateway->addOrder($order);
				$orderId = sprintf('2006%d', $lastInsertOrderId);
			}

			// Basket aktualisieren
			if($this->_feuser instanceof Member_Model_DbTable_Feuser_Row) {
				$basket->setGateway($basketGateway);
				$basket->saveFeuserId($this->_feuser->id);
			}

			// Coupon aktualisieren
			if($couponIsValid) {
				$coupon->setGateway(new Sherpa_Model_CouponGateway());
				$cashedCouponValue = $coupon->cashIn($subtotal, $basket->getId());
			}

			$this->assignToView('orderId', $orderId);
			$this->assignToView('orderDate', $this->_view->date('FFFF').' '.$this->_view->date('TT'));
			$this->assignToView('cashedCouponValue', empty($cashedCouponValue) ? 0 : $cashedCouponValue);
			$this->assignToView('products', $products);
			$this->assignToView('coupon', $coupon);
			$this->assignToView('medialist', $medialist);

			// Konfigurationseinstellungen
			$config = $this->getConfiguration();

			// E-Mail an Sherpa
			$confirmationInternal = $this->_view->render('checkout/mail/order_internal.phtml');
			$mail = new Zend_Mail('utf-8');
			$mail->setSubject('Sherpa Outdoor [Bestellung ' . $orderId . ']');
			$mail->setBodyText($confirmationInternal);
			$mail->setFrom($config->senderEmail, $config->senderName);
			$mail->addTo($config->recipientEmail, $config->recipientName);
			$mail->send();
			$orderGateway->updateOrder(array('confirmationInternal' => $confirmationInternal), $lastInsertOrderId);

			// E-Mail an Besteller
			$confirmationOrder = $this->_view->render('checkout/mail/order_confirmation.phtml');
			$mail = new Zend_Mail('utf-8');
			$mail->setSubject('Sherpa Outdoor [Bestellung ' . $orderId . ']');
			$mail->setBodyText($confirmationOrder);
			$mail->setFrom($config->senderEmail, $config->senderName);
			$mail->addTo($billingAddress->getEmail(), $billingAddress->getName());
			$mail->send();
			$orderGateway->updateOrder(array('confirmationOrder' => $confirmationOrder), $lastInsertOrderId);

			$this->confirmationAction();
			return;
		} else {
			$this->summaryAction($errors);
		}
	}

	/**
	 * Confirmation Action
	 */
	public function confirmationAction()
	{
		// Validierung der Session Daten
		if(!$this->_validateSessionAddressData()) {
			$this->renderView('checkout/error.phtml');
			return;
		}

		$this->renderView('checkout/confirmation.phtml');

		// Loeschen der Session Daten
		if(!$this->_test) {
			$this->_session->unsetAll();
		}

	}

	/**
	 * @return boolean
	 */
	private function _validateSessionAddressData()
	{
		$isValid = true;
		// Validierung der in der Session gespeicherten Daten
		if($this->_isAnonymousCheckout()) {
			// Die Liefer- und Rechnungsadresse sind in der Session gespeichert
			$form = new Sherpa_Form_Address();
			if(!$form->isValid($this->_session->shippingAddress)) {
				$isValid = false;
			}
			if(!$form->isValid($this->_session->billingAddress)) {
				$isValid = false;
			}
		} else {
			// Es sind nur die IDs der ausgewahlten Datensaetze gespeichert
			if(empty($this->_session->shippingAddressId)) {
				$isValid = false;
			} else {
				$gateway = new Sherpa_Model_AddressGateway();
				// Lieferadresse auf Existenz in der DB pruefen
				$shippingAddress = $gateway->fetchAddress($this->_session->shippingAddressId);
				if($shippingAddress->isEmpty()) {
					$isValid = false;
				}
			}
			if(empty($this->_session->billingAddressId)) {
				$isValid = false;
			} else {
				$gateway = new Sherpa_Model_AddressGateway();
				// Rechnungsadresse auf Existenz in der DB pruefen
				$billingAddress = $gateway->fetchAddress($this->_session->billingAddressId);
				if($billingAddress->isEmpty()) {
					$isValid = false;
				}
			}
		}
		return $isValid;
	}

	/**
	 * @return void
	 */
	private function _assignSessionDataToView()
	{
		$this->assignToView('shippingAddress', $this->_getShippingAddressFromSession());
		$this->assignToView('billingAddress', $this->_getBillingAddressFromSession());
		$this->assignToView('sameAsShippingAddress', (bool)$this->_session->sameAsShippingAddress);
	}

	/**
	 * @return Sherpa_Model_Address
	 */
	private function _getShippingAddressFromSession()
	{
		$shippingAddress = null;
		if($this->_isAnonymousCheckout()) {
			$shippingAddress = new Sherpa_Model_Address($this->_session->shippingAddress);
		} else {
			$gateway = new Sherpa_Model_AddressGateway();
			$shippingAddress = $gateway->fetchAddress($this->_session->shippingAddressId);
		}
		return $shippingAddress;
	}

	/**
	 * @return Sherpa_Model_Address
	 */
	private function _getBillingAddressFromSession()
	{
		$billingAddress = null;
		if($this->_isAnonymousCheckout()) {
			$billingAddress = new Sherpa_Model_Address($this->_session->billingAddress);
		} else {
			$gateway = new Sherpa_Model_AddressGateway();
			$billingAddress = $gateway->fetchAddress($this->_session->billingAddressId);
		}
		return $billingAddress;
	}

	/**
	 * @return boolean
	 */
	private function _isValid()
	{
		if($this->_feuser instanceof Member_Model_DbTable_Feuser_Row) {
			return true;
		} elseif(!empty($this->_session->baEmail)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * @return void
	 */
	private function _redirectToCart()
	{
		$pageId = $this->getConfiguration()->pageIdCart;
		$url = WSB_Xtension_Url::getInstance()->getHrefToPage($pageId);
		$this->redirect($url);
	}

	/**
	 * @return boolean
	 */
	private function _isAnonymousCheckout()
	{
		return !($this->_feuser instanceof Member_Model_DbTable_Feuser_Row);
	}

	/**
	 * @return Sherpa_Model_BasketProducts
	 */
	private function _getBasketProducts()
	{
		$languageId = $this->getLanguageId();
		$gateway = new Sherpa_Model_BasketGateway();
		$products = $gateway->fetchProducts($languageId);
		$products->loadColorApplications();
		$products->loadMainImages($languageId);
		$products->loadImageVariants();
		return $products;
	}

	/**
	 * @param
	 */
	private function _getCoupon()
	{
		$couponCode = trim($this->_session->couponCode);
		$gateway = new Sherpa_Model_CouponGateway();
		return $gateway->fetchCoupon($couponCode);
	}

	/**
	 * @return Sherpa_Model_Addresses
	 */
	private function _getFeuserAddresses()
	{
		$gateway = new Sherpa_Model_AddressGateway();
		$addresses = $gateway->fetchAddresses();
		return $addresses;
	}

	/**
	 * @return boolean
	 */
	private function _createButtonClicked()
	{
		$request = $this->getRequest();
		return ($request->getPost('btnCreateAddress') != '')	// Button
		 || ($request->getPost('btnCreateAddress_x') != '')		// Image button
		 || ($request->getPost('btnCreateAddress_y') != '');	// Image button
	}

}
